﻿using Microsoft.SqlServer.TransactSql.ScriptDom;

namespace zijian666.Data.SqlBuilders;

class SqlServerBuilder : TSqlBuilder
{
    public static readonly SqlServerBuilder Instance = new();

    public override string PagingSql(string sql, long begin, int count)
    {
        // 使用 TSql150Parser 来解析 SQL
        var parser = TSqlParser.CreateParser(SqlVersion.Sql170, true); // 设置为 true 表示忽略大小写

        using var reader = new StringReader(sql);
        var script = (TSqlScript)parser.Parse(reader, out var errors);
        if (errors.Count > 0)
        {
            throw new InvalidOperationException(string.Join(Environment.NewLine, errors));
        }

        if (script?.Batches?.Count is null or 0)
        {
            return sql;
        }
        if (script.Batches.Count > 1)
        {
            throw new NotSupportedException("不支持多个批次的 SQL");
        }

        var orderby = (script.Batches[0].Statements[0] as SelectStatement)?.QueryExpression.OrderByClause;
        if (orderby is null)
        {
            return $"{sql.TrimSemicolon()} ORDER BY (SELECT NULL) OFFSET {begin} ROWS FETCH NEXT {count} ROWS ONLY;";
        }
        return $"{sql.TrimSemicolon()} OFFSET {begin} ROWS FETCH NEXT {count} ROWS ONLY;";
    }


    public virtual string RemoveTopOrderBy(string sql)
    {
        // 使用 TSql150Parser 来解析 SQL
        var parser = TSqlParser.CreateParser(SqlVersion.Sql170, true); // 设置为 true 表示忽略大小写

        // 将 SQL 字符串解析为 TSqlFragment
        using var reader = new StringReader(sql);
        var script = (TSqlScript)parser.Parse(reader, out var errors);
        if (errors.Count > 0)
        {
            throw new InvalidOperationException(string.Join(Environment.NewLine, errors));
        }

        if (script?.Batches?.Count is null or 0)
        {
            return sql;
        }
        if (script.Batches.Count > 1)
        {
            throw new NotSupportedException("不支持多个批次的 SQL");
        }

        var orderby = (script.Batches[0].Statements[0] as SelectStatement)?.QueryExpression.OrderByClause;
        if (orderby is null)
        {
            return sql;
        }

        return sql.Remove(orderby.StartOffset, orderby.FragmentLength);
    }


    private DbProviderFactory _dbProvider = default!;

    public override DbProviderFactory DbProvider
    {
        get
        {
            if (_dbProvider is null)
            {
                if (DbProviderFactories.TryGetFactory("System.Data.SqlClient", out _dbProvider!))
                {
                    return _dbProvider;
                }
                if (DbProviderFactories.TryGetFactory("Microsoft.Data.SqlClient", out _dbProvider!))
                {
                    return _dbProvider;
                }
                throw new NotSupportedException("未找到 SqlServer 提供程序");
            }
            return _dbProvider;
        }
    }


    public override string GetParameterHolder(string parameterName)
    {
        return $"@{parameterName}";
    }
}
